import { Client } from '@stomp/stompjs';

const StompService = {
    client: null,
    connected: false,
    connectPromise: null,
    subscriptions: {},

    async connect(wsEndpoint, connectHeaders = {}) {
        if (this.client && this.connected) return Promise.resolve(this.client);
        if (this.connectPromise) return this.connectPromise;

        // Lazy-load sockjs-client to avoid module evaluation time errors
        // (some bundlers or libs expect `global` to exist during import)
        let SockJS = null;
        try {
            const mod = await
            import ('sockjs-client');
            SockJS = mod && (mod.default || mod);
        } catch (e) {
            console.warn('Failed to lazy-load sockjs-client, SockJS may be unavailable', e);
        }

        this.client = new Client({
            webSocketFactory: SockJS ? (() => new SockJS(wsEndpoint)) : undefined,
            debug: (msg) => { /* console.debug('[STOMP]', msg); */ },
            reconnectDelay: 5000,
            heartbeatIncoming: 0,
            heartbeatOutgoing: 20000,
        });

        if (connectHeaders && Object.keys(connectHeaders).length) {
            this.client.connectHeaders = connectHeaders;
        }

        this.connectPromise = new Promise((resolve, reject) => {
            this.client.onConnect = (frame) => {
                this.connected = true;
                resolve(this.client);
            };
            this.client.onStompError = (frame) => {
                console.error('STOMP error', frame);
            };
            this.client.onWebSocketClose = () => { this.connected = false; };
            this.client.onWebSocketError = (err) => { console.error('WS error', err); };

            try { this.client.activate(); } catch (e) { reject(e); }
        });

        return this.connectPromise;
    },

    async subscribeRoutingTable(simulationId, routerId, onMessage) {
        if (!simulationId || !routerId) throw new Error('simulationId and routerId required');
        const key = `${simulationId}:${routerId}`;
        this.unsubscribe(simulationId, routerId);
        const dest = `/topic/simulations/${simulationId}/routers/${routerId}/routing-table`;
        const sub = this.client.subscribe(dest, (msg) => {
            let parsed = null;
            try { parsed = JSON.parse(msg.body); } catch (e) { parsed = msg.body; }
            onMessage && onMessage(parsed);
        });
        this.subscriptions[key] = sub;
        return sub;
    },

    unsubscribe(simulationId, routerId) {
        const key = `${simulationId}:${routerId}`;
        const sub = this.subscriptions[key];
        if (sub) {
            try { sub.unsubscribe(); } catch (e) {}
            delete this.subscriptions[key];
        }
    },

    async disconnect() {
        try {
            Object.keys(this.subscriptions).forEach(k => {
                try { this.subscriptions[k].unsubscribe(); } catch (e) {}
            });
            this.subscriptions = {};
            if (this.client) { this.client.deactivate(); }
        } finally {
            this.client = null;
            this.connected = false;
            this.connectPromise = null;
        }
    }
};

export default StompService;